﻿/*!	@file	r_type_f16.h
	@brief	16bit浮動小数型
Copyright (c) 2010 Yuya Yamaguchi

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
*/
#ifndef _R_TYPE_F16_H_
#define _R_TYPE_F16_H_

class cRFP16;
typedef	cRFP16				r_f16;
typedef r_si16				r_f16val;

class cRFP16
{
public:
	cRFP16() {}
	r_f16val		get ( void ) const {
		return val;
	}
	void			set ( r_f32 f32val ) {
		val = convertionFromF32 ( f32val );
	}
public:
	// 初期化代入系
	cRFP16 ( const cRFP16 &f16val )
		:
		val ( f16val ) {
	}
	cRFP16 ( r_f32 f32val )
		:
		val ( convertionFromF32 ( f32val ) ) {
	}
	const cRFP16	&operator = ( r_f32 f32val ) {
		set ( f32val );
		return *this;
	}
	const cRFP16	&operator = ( cRFP16 f16val ) {
		val = f16val;
		return *this;
	}
	operator		r_f16val() const {
		return val;
	}
	operator		r_f32() const {
		return convertionToF32 ( val );
	}
public:
	//!< 比較演算子系
	r_bool			operator == ( const r_f16 &a ) const {
		return convertionToF32 ( val ) == convertionToF32 ( a.val );
	}
	r_bool			operator == ( const r_f32 &a ) const {
		return convertionToF32 ( val ) == a;
	}
	r_bool			operator != ( const r_f16 &a ) const {
		return convertionToF32 ( val ) != convertionToF32 ( a.val );
	}
	r_bool			operator != ( const r_f32 &a ) const {
		return convertionToF32 ( val ) != a;
	}
	r_bool			operator < ( const r_f16 &a ) const {
		return convertionToF32 ( val ) < convertionToF32 ( a.val );
	}
	r_bool			operator < ( const r_f32 &a ) const {
		return convertionToF32 ( val ) < a;
	}
	r_bool			operator <= ( const r_f16 &a ) const {
		return convertionToF32 ( val ) <= convertionToF32 ( a );
	}
	r_bool			operator <= ( const r_f32 &a ) const {
		return convertionToF32 ( val ) <= a;
	}
	r_bool			operator > ( const r_f16 &a ) const {
		return convertionToF32 ( val ) > convertionToF32 ( a );
	}
	r_bool			operator > ( const r_f32 &a ) const {
		return convertionToF32 ( val ) > a;
	}
	r_bool			operator >= ( const r_f16 &a ) const {
		return convertionToF32 ( val ) >= convertionToF32 ( a );
	}
	r_bool			operator >= ( const r_f32 &a ) const {
		return convertionToF32 ( val ) >= a;
	}
public:
	// 加算
	r_f16			operator + ( const r_f16 &a ) const {
		return r_f16 ( convertionToF32 ( val ) + convertionToF32 ( a ) );
	}
	r_f16			operator + ( const r_f32 &a ) const {
		return r_f16 ( convertionToF32 ( val ) + a );
	}
	const r_f16		&operator += ( const r_f16 &a ) {
		val = convertionFromF32 ( convertionToF32 ( val ) + convertionToF32 ( a ) );
		return *this;
	}
	const r_f16		&operator += ( const r_f32 &a ) {
		val = convertionFromF32 ( convertionToF32 ( val ) + a );
		return *this;
	}
	// 減算
	r_f16			operator - ( const r_f16 &a ) const {
		return r_f16 ( convertionToF32 ( val ) - convertionToF32 ( a ) );
	}
	r_f16			operator - ( const r_f32 &a ) const {
		return r_f16 ( convertionToF32 ( val ) - a );
	}
	const r_f16		&operator -= ( const r_f16 &a ) {
		val = convertionFromF32 ( convertionToF32 ( val ) - convertionToF32 ( a ) );
		return *this;
	}
	const r_f16		&operator -= ( const r_f32 &a ) {
		val = convertionFromF32 ( convertionToF32 ( val ) - a );
		return *this;
	}
	// 乗算
	r_f16			operator * ( const r_f16 &a ) const {
		return r_f16 ( convertionToF32 ( val ) * convertionToF32 ( a ) );
	}
	r_f16			operator * ( const r_f32 &a ) const {
		return r_f16 ( convertionToF32 ( val ) * a );
	}
	const r_f16		&operator *= ( const r_f16 &a ) {
		val = convertionFromF32 ( convertionToF32 ( val ) * convertionToF32 ( a ) );
		return *this;
	}
	const r_f16		&operator *= ( const r_f32 &a ) {
		val = convertionFromF32 ( convertionToF32 ( val ) * a );
		return *this;
	}
	// 除算
	r_f16			operator / ( const r_f16 &a ) const {
		return r_f16 ( convertionToF32 ( val ) / convertionToF32 ( a ) );
	}
	r_f16			operator / ( const r_f32 &a ) const {
		return r_f16 ( convertionToF32 ( val ) / a );
	}
	const r_f16		&operator /= ( const r_f16 &a ) {
		val = convertionFromF32 ( convertionToF32 ( val ) / convertionToF32 ( a ) );
		return *this;
	}
	const r_f16		&operator /= ( const r_f32 &a ) {
		val = convertionFromF32 ( convertionToF32 ( val ) / a );
		return *this;
	}
public:
	//! 32bit浮動少数から16bit浮動少数に変換
	static r_f16val			convertionFromF32 ( r_f32 f32val ) {
		r_ui32 itbit = *reinterpret_cast<r_ui32*> ( &f32val );
		if ( itbit == 0 ) {
			return 0;
		}
		// 指数部分処理
		r_si32 e = ( ( itbit & 0x7f800000 ) >> 23 ) - 127 + 15;
		if ( e < 0 ) {
			return 0;
		} else if ( e > 31 ) {
			e = 31;
		}
		// 符号ビット
		r_ui32 s = itbit & 0x80000000;
		// 仮数ビット
		r_ui32 f = itbit & 0x007fffff;
		return static_cast<r_si16> ( ( s >> 16 ) & 0x8000 ) | ( ( e << 10 ) & 0x7c00 ) | ( ( f >> 13 ) & 0x03ff );
	}
	//! 16bit浮動少数から32bit浮動少数に変換
	static r_f32			convertionToF32 ( r_f16val f16val ) {
		if ( f16val == 0 ) {
			return	0.0f;
		}
		// 符号ビット
		r_ui32 s =  f16val & 0x8000;
		r_si32 e = ( ( f16val & 0x7c00 ) >> 10 ) - 15 + 127;
		r_ui32 f =  f16val & 0x03ff;
		r_ui32 fval = ( s << 16 ) | ( ( e << 23 ) & 0x7f800000 ) | ( f << 13 );
		return	* reinterpret_cast<float*> ( &fval );
	}
private:
	//! 変数値
	r_f16val			val;
};


#endif _R_TYPE_F16_H_

